<?php
	/* Functions in this file */
	/**************************/

	// AddComplexSymbol($symbolData)
	// ClearBeam()
	// ClearBeamingFlag($flag)
	// ClearComplexSymbolArrayContents()
	// ClearDataFlag($flag)
	// ClearIrregularGroupingTiming()
	// ClearMultibarRest()
	// ClearTremoloBar()
	// ClearVolumeSwell()
	// FindComplexSymbol($type)
	// GetComplexSymbolCount()
	// GetDurationType()
	// GetMFCClassName()
	// GetMFCClassSchema()
	// GetMultibarRest(&$measureCount)
	// GetNote($index)
	// GetNoteCount()
	// GetPosition()
	// GetPreviousBeamDurationType()
	// HasArpeggioDown()
	// HasArpeggioUp()
	// HasFermata()
	// HasFractionalLeftBeam()
	// HasFractionalRightBeam()
	// HasIrregularGroupingTiming()
	// HasLetRing()
	// HasMarcato()
	// HasMultibarRest()
	// HasPalmMuting()
	// HasPickStrokeDown()
	// HasPickStrokeUp()
	// HasSforzando()
	// HasTap()
	// HasTremoloBar()
	// HasTremoloPicking()
	// HasVibrato()
	// HasVolumeSwell()
	// HasWideVibrato()
	// IsAcciaccatura()
	// IsBeamEnd()
	// IsBeamingFlagSet($flag)
	// IsBeamStart()
	// IsDataFlagSet($flag)
	// IsDotted()
	// IsDoubleDotted()
	// IsIrregularGroupingEnd()
	// IsIrregularGroupingMiddle()
	// IsIrregularGroupingStart()
	// IsRest()
	// IsStaccato()
	// IsTripletFeel1st()
	// IsTripletFeel2nd()
	// IsValidBeamingFlag($flag)
	// IsValidComplexSymbolType($type)
	// IsValidDataFlag($flag)
	// IsValidDurationType($durationType)
	// IsValidMultibarRest($measureCount)
	// IsValidMultibarRestMeasureCount($measureCount)
	// IsValidNoteIndex($index)
	// IsValidPosition($position)
	// IsValidPreviousBeamDurationType($durationType)
	// IsValidTremoloBarDuration($duration)
	// IsValidTremoloBarPitch($pitch)
	// IsValidTremoloBarType($type)
	// RemoveComplexSymbol($type)
	// SetBeamingFlag($flag)
	// SetDataFlag($flag)
	// SetDurationType($durationType)
	// SetMultibarRest($measureCount)
	// SetPosition($position)
	// SetPreviousBeamDurationType($durationType)
?>
<?php
	 
	 
	 
	 
	define('MAX_POSITION_COMPLEX_SYMBOLS',2);
	 
	 
	class Position {
		 
		 
		// Constants
		// Default Constants
		const DEFAULT_POSITION = 0;
		const DEFAULT_BEAMING = 0;
		const DEFAULT_DATA = 0x08000000;
		const DEFAULT_DURATION_TYPE = 8;
		 
		// $this->Position Constants
		const MIN_POSITION = 0;
		const MAX_POSITION = 255;
		 
		// Irregular Grouping Constants
		const MIN_IRREGULAR_GROUPING_NOTES_PLAYED = 2;
		const MAX_IRREGULAR_GROUPING_NOTES_PLAYED = 16;
		const MIN_IRREGULAR_GROUPING_NOTES_PLAYED_OVER = 2;
		const MAX_IRREGULAR_GROUPING_NOTES_PLAYED_OVER = 8;
		 
		const MAX_VOLUME_SWELL_DURATION = 8;
		 
		const MAX_TREMOLO_BAR_DURATION = 8;
		const MAX_TREMOLO_BAR_PITCH = 28;
		 
		// Multibar Rest Constants
		const MIN_MULTIBAR_REST_MEASURE_COUNT = 2;
		const MAX_MULTIBAR_REST_MEASURE_COUNT = 255;
		 
		 
		const irregularGroupingNotesPlayedOverMask = 0x00000007;
		const irregularGroupingNotesPlayedMask = 0x00000078;
		const irregularGroupingTimingMask = 0x0000007f;
		 
		const previousBeamDuration8th = 0x00000001;
		const previousBeamDuration16th = 0x00000002;
		const previousBeamDuration32nd = 0x00000003;
		const previousBeamDuration64th = 0x00000004;
		const previousBeamDurationTypeMask = 0x00000380;
		 
		const beamStart = 0x00000400;
		const beamFractionalLeft = 0x00000800;
		const beamFractionalRight = 0x00001000;
		const beamEnd = 0x00002000;
		 
		const beamingFlagsMask = 0x00003f80;
		 
		 
		 
		// Simple $flags
		 
		const dotted = 0x00000001;
		const doubleDotted = 0x00000002;
		const dottedMask = 0x00000003;
		 
		const rest = 0x00000004;
		 
		const vibrato = 0x00000008;
		const wideVibrato = 0x00000010;
		const vibratoMask = 0x00000018;
		 
		const arpeggioUp = 0x00000020;
		const arpeggioDown = 0x00000040;
		const arpeggioMask = 0x00000060;
		 
		const pickStrokeUp = 0x00000080;
		const pickStrokeDown = 0x00000100;
		const pickStrokeMask = 0x00000180;
		 
		const staccato = 0x00000200;
		 
		const marcato = 0x00000400;
		const sforzando = 0x00000800;
		const accentMask = 0x00000c00;
		 
		const tremoloPicking = 0x00001000;
		const palmMuting = 0x00002000;
		const tap = 0x00004000;
		const appoggiatura = 0x00008000;
		const acciaccatura = 0x00010000;
		 
		const tripletFeel1st = 0x00020000;
		const tripletFeel2nd = 0x00040000;
		const tripletFeelMask = 0x00060000;
		 
		const letRing = 0x00080000;
		const fermata = 0x00100000;
		const irregularGroupingStart = 0x00200000;
		const irregularGroupingMiddle = 0x00400000;
		const irregularGroupingEnd = 0x00800000;
		const irregularGroupingFlagsMask = 0x00e00000;
		 
		const dataFlagsMask = 0x00ffffff;
		const durationTypeMask = 0x7f000000;
		 
		 
		 
		const volumeSwell = 97; //'a';
		const tremoloBar = 99; //'c';
		const multibarRest = 106; //'j';
		const notUsed = 0;
		 
		 
		 
		const dip = 0x00000000;
		const diveAndRelease = 0x00000001;
		const diveAndHold = 0x00000002;
		const release = 0x00000003;
		const returnAndRelease = 0x00000004;
		const returnAndHold = 0x00000005;
		const invertedDip = 0x00000006;
		 
		 
		 
		protected $m_position = self::DEFAULT_POSITION;
		protected $m_beaming = self::DEFAULT_BEAMING;
		protected $m_data = self::DEFAULT_DATA;
		protected $m_complexSymbolArray = array ();
		 
		public $m_noteArray = array ();
		 
		 
		 
		function GetMFCClassName() {
			return "CPosition";
		}
		 
		 
		function GetMFCClassSchema() {
			return 1;
		}
		 
		// $this->Position Functions
		 
		 
		 
		function IsValidPosition($position) {
			return (($position >= self::MIN_POSITION) && ($position <= self::MAX_POSITION));
		}
		 
		 
		 
		function SetPosition($position) {
			if (!$this->IsValidPosition($position)) return 0;
			$this->m_position = $position;
			 return 1;
		}
		 
		 
		function GetPosition() {
			return ($this->m_position);
		}
		 
		// Duration Type Functions
		 
		 
		 
		function IsValidDurationType($durationType) {
			return (($durationType == 1) || ($durationType == 2) || ($durationType == 4) || ($durationType == 8) || ($durationType == 16) || ($durationType == 32) || ($durationType == 64));
		}
		 
		 
		// Irregular Grouping Functions
		 
		 
		function IsValidIrregularGroupingTiming($notesPlayed, $notesPlayedOver) {
			return (($notesPlayed >= self::MIN_IRREGULAR_GROUPING_NOTES_PLAYED) && ($notesPlayed <= self::MAX_IRREGULAR_GROUPING_NOTES_PLAYED)) && (($notesPlayedOver >= self::MIN_IRREGULAR_GROUPING_NOTES_PLAYED_OVER) && ($notesPlayedOver <= self::MAX_IRREGULAR_GROUPING_NOTES_PLAYED_OVER));
		}
		 
		// Previous Beam Duration Functions
		 
		 
		 
		function IsValidPreviousBeamDurationType($durationType) {
			return (($durationType == 0) || ($durationType == 8) || ($durationType == 16) || ($durationType == 32) || ($durationType == 64));
		}
		 
		 
		function SetBeamStart($set = 1) {
			if (!$set) return ($this->ClearBeamingFlag(self::beamStart));
				 return ($this->SetBeamingFlag(self::beamStart));
		}
		 
		 
		function IsBeamStart() {
			return ($this->IsBeamingFlagSet(self::beamStart));
		}
		 
		 
		 
		function SetFractionalLeftBeam($set = 1) {
			if (!$set) return ($this->ClearBeamingFlag(self::beamFractionalLeft));
				 return ($this->SetBeamingFlag(self::beamFractionalLeft));
		}
		 
		 
		function HasFractionalLeftBeam() {
			return ($this->IsBeamingFlagSet(self::beamFractionalLeft));
		}
		 
		 
		 
		function SetFractionalRightBeam($set = 1) {
			if (!$set) return ($this->ClearBeamingFlag(self::beamFractionalRight));
				 return ($this->SetBeamingFlag(self::beamFractionalRight));
		}
		 
		 
		function HasFractionalRightBeam() {
			return ($this->IsBeamingFlagSet(self::beamFractionalRight));
		}
		 
		 
		 
		function SetBeamEnd($set = 1) {
			if (!$set) return ($this->ClearBeamingFlag(self::beamEnd));
				 return ($this->SetBeamingFlag(self::beamEnd));
		}
		 
		 
		function IsBeamEnd() {
			return ($this->IsBeamingFlagSet(self::beamEnd));
		}
		 
		 
		function ClearBeam() {
			return ($this->ClearBeamingFlag(self::beamingFlagsMask));
		}
		 
		 
		 
		 
		 
		function IsValidBeamingFlag($flag) {
			return ((($flag & self::beamingFlagsMask) != 0) && (($flag & ~self::beamingFlagsMask) == 0));
		}
		 
		 
		function ClearBeamingFlag($flag) {
			if (!$this->IsValidBeamingFlag($flag)) return 0;
			$this->m_beaming &= ~$flag;
			 return 1;
		}
		 
		 
		 
		function IsBeamingFlagSet($flag) {
			if (!$this->IsValidBeamingFlag($flag)) return 0;
			 return (($this->m_beaming & $flag) == $flag);
		}
		 
		// Dotted Functions
		 
		 
		 
		function SetDotted($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::dotted));
				 return ($this->SetDataFlag(self::dotted));
		}
		 
		 
		function IsDotted() {
			return ($this->IsDataFlagSet(self::dotted));
		}
		 
		// Double Dotted Functions
		 
		 
		 
		function SetDoubleDotted($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::doubleDotted));
				 return ($this->SetDataFlag(self::doubleDotted));
		}
		 
		 
		function IsDoubleDotted() {
			return ($this->IsDataFlagSet(self::doubleDotted));
		}
		 
		// Rest Functions
		 
		 
		 
		function SetRest($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::rest));
				 return ($this->SetDataFlag(self::rest));
		}
		 
		 
		function IsRest() {
			return ($this->IsDataFlagSet(self::rest));
		}
		 
		// Vibrato Functions
		 
		 
		 
		function SetVibrato($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::vibrato));
				 return ($this->SetDataFlag(self::vibrato));
		}
		 
		 
		function HasVibrato() {
			return ($this->IsDataFlagSet(self::vibrato));
		}
		 
		// Wide Vibrato Functions
		 
		 
		 
		function SetWideVibrato($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::wideVibrato));
				 return ($this->SetDataFlag(self::wideVibrato));
		}
		 
		 
		function HasWideVibrato() {
			return ($this->IsDataFlagSet(self::wideVibrato));
		}
		 
		// Arpeggio Up Functions
		 
		 
		 
		function SetArpeggioUp($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::arpeggioUp));
				 return ($this->SetDataFlag(self::arpeggioUp));
		}
		 
		 
		function HasArpeggioUp() {
			return ($this->IsDataFlagSet(self::arpeggioUp));
		}
		 
		// Arpeggio Down Functions
		 
		 
		 
		function SetArpeggioDown($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::arpeggioDown));
				 return ($this->SetDataFlag(self::arpeggioDown));
		}
		 
		 
		function HasArpeggioDown() {
			return ($this->IsDataFlagSet(self::arpeggioDown));
		}
		 
		// Pick Stroke Up Functions
		 
		 
		 
		function SetPickStrokeUp($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::pickStrokeUp));
				 return ($this->SetDataFlag(self::pickStrokeUp));
		}
		 
		 
		function HasPickStrokeUp() {
			return ($this->IsDataFlagSet(self::pickStrokeUp));
		}
		 
		// Pick Stroke Down Functions
		 
		 
		 
		function SetPickStrokeDown($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::pickStrokeDown));
				 return ($this->SetDataFlag(self::pickStrokeDown));
		}
		 
		 
		function HasPickStrokeDown() {
			return ($this->IsDataFlagSet(self::pickStrokeDown));
		}
		 
		// Staccato Functions
		 
		 
		 
		function SetStaccato($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::staccato));
				 return ($this->SetDataFlag(self::staccato));
		}
		 
		 
		function IsStaccato() {
			return ($this->IsDataFlagSet(self::staccato));
		}
		 
		// Marcato Functions
		 
		 
		 
		function SetMarcato($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::marcato));
				 return ($this->SetDataFlag(self::marcato));
		}
		 
		 
		function HasMarcato() {
			return ($this->IsDataFlagSet(self::marcato));
		}
		 
		// Sforzando Functions
		 
		 
		 
		function SetSforzando($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::sforzando));
				 return ($this->SetDataFlag(self::sforzando));
		}
		 
		 
		function HasSforzando() {
			return ($this->IsDataFlagSet(self::sforzando));
		}
		 
		// Tremolo Picking Functions
		 
		 
		 
		function SetTremoloPicking($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::tremoloPicking));
				 return ($this->SetDataFlag(self::tremoloPicking));
		}
		 
		 
		function HasTremoloPicking() {
			return ($this->IsDataFlagSet(self::tremoloPicking));
		}
		 
		// Palm Muting Functions
		 
		 
		 
		function SetPalmMuting($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::palmMuting));
				 return ($this->SetDataFlag(self::palmMuting));
		}
		 
		 
		function HasPalmMuting() {
			return ($this->IsDataFlagSet(self::palmMuting));
		}
		 
		// Tap Functions
		 
		 
		 
		function SetTap($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::tap));
				 return ($this->SetDataFlag(self::tap));
		}
		 
		 
		function HasTap() {
			return ($this->IsDataFlagSet(self::tap));
		}
		 
		// Acciaccatura Functions
		 
		 
		 
		function SetAcciaccatura($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::acciaccatura));
				 return ($this->SetDataFlag(self::acciaccatura));
		}
		 
		 
		function IsAcciaccatura() {
			return ($this->IsDataFlagSet(self::acciaccatura));
		}
		 
		// Triplet Feel 1st Functions
		 
		 
		 
		function SetTripletFeel1st($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::tripletFeel1st));
				 return ($this->SetDataFlag(self::tripletFeel1st));
		}
		 
		 
		function IsTripletFeel1st() {
			return ($this->IsDataFlagSet(self::tripletFeel1st));
		}
		 
		// Triplet Feel 2nd Functions
		 
		 
		 
		function SetTripletFeel2nd($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::tripletFeel2nd));
				 return ($this->SetDataFlag(self::tripletFeel2nd));
		}
		 
		 
		function IsTripletFeel2nd() {
			return ($this->IsDataFlagSet(self::tripletFeel2nd));
		}
		 
		// Let Ring Functions
		 
		 
		 
		function SetLetRing($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::letRing));
				 return ($this->SetDataFlag(self::letRing));
		}
		 
		 
		function HasLetRing() {
			return ($this->IsDataFlagSet(self::letRing));
		}
		 
		// Fermata Functions
		 
		 
		 
		function SetFermata($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::fermata));
				 return ($this->SetDataFlag(self::fermata));
		}
		 
		 
		function HasFermata() {
			return ($this->IsDataFlagSet(self::fermata));
		}
		 
		// Irregular Grouping Functions
		 
		 
		 
		function SetIrregularGroupingStart($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::irregularGroupingStart));
				 return ($this->SetDataFlag(self::irregularGroupingStart));
		}
		 
		 
		function IsIrregularGroupingStart() {
			return ($this->IsDataFlagSet(self::irregularGroupingStart));
		}
		 
		 
		 
		 
		function SetIrregularGroupingMiddle($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::irregularGroupingMiddle));
				 return ($this->SetDataFlag(self::irregularGroupingMiddle));
		}
		 
		 
		function IsIrregularGroupingMiddle() {
			return ($this->IsDataFlagSet(self::irregularGroupingMiddle));
		}
		 
		 
		 
		 
		function SetIrregularGroupingEnd($set = 1) {
			if (!$set) return ($this->ClearDataFlag(self::irregularGroupingEnd));
				 return ($this->SetDataFlag(self::irregularGroupingEnd));
		}
		 
		 
		function IsIrregularGroupingEnd() {
			return ($this->IsDataFlagSet(self::irregularGroupingEnd));
		}
		 
		 
		// Flag Functions
		 
		 
		 
		function IsValidDataFlag($flag) {
			return ((($flag & self::dataFlagsMask) != 0) && (($flag & ~self::dataFlagsMask) == 0));
		}
		 
		 
		 
		function ClearDataFlag($flag) {
			if (!$this->IsValidDataFlag($flag)) return 0;
			$this->m_data &= ~$flag;
			 return 1;
		}
		 
		 
		 
		function IsDataFlagSet($flag) {
			if (!$this->IsValidDataFlag($flag)) return 0;
			 return (($this->m_data & $flag) == $flag);
		}
		 
		// Volume Swell Functions
		function IsValidVolumeSwell($startVolume, $endVolume, $duration) {
			return (
			(Dynamic::IsValidVolume($startVolume) && $startVolume != Dynamic::notSet) && (Dynamic::IsValidVolume($endVolume) && $endVolume != Dynamic::notSet) && ($startVolume != $endVolume) && ($duration <= self::MAX_VOLUME_SWELL_DURATION)
			);
		}
		 
		 
		// Tremolo Bar Functions
		 
		 
		 
		function IsValidTremoloBarType($type) {
			return ($type <= self::invertedDip);
		}
		 
		 
		 
		function IsValidTremoloBarDuration($duration) {
			return ($duration <= self::MAX_TREMOLO_BAR_DURATION);
		}
		 
		 
		 
		function IsValidTremoloBarPitch($pitch) {
			return ($pitch <= self::MAX_TREMOLO_BAR_PITCH);
		}
		 
		 
		 
		 
		 
		function IsValidTremoloBar($type, $duration, $pitch) {
			return (
			($this->IsValidTremoloBarType($type)) && ($this->IsValidTremoloBarDuration($duration)) && ($this->IsValidTremoloBarPitch($pitch))
			);
		}
		 
		 
		// Multibar Rest Functions
		 
		 
		 
		function IsValidMultibarRestMeasureCount($measureCount) {
			return (($measureCount >= self::MIN_MULTIBAR_REST_MEASURE_COUNT) && ($measureCount <= self::MAX_MULTIBAR_REST_MEASURE_COUNT));
		}
		 
		 
		 
		function IsValidMultibarRest($measureCount) {
			return ($this->IsValidMultibarRestMeasureCount($measureCount));
		}
		 
		 
		// Complex Symbol Array Functions
		 
		 
		 
		function IsValidComplexSymbolType($type) {
			return (($type == self::volumeSwell) || ($type == self::tremoloBar) || ($type == self::multibarRest));
		}
		 
		 
		// Note Functions
		 
		 
		 
		function IsValidNoteIndex($index) {
			return ($index < $this->GetNoteCount());
		}
		 
		 
		function GetNoteCount() {
			return sizeof($this->m_noteArray);
		}
		 
		 
		 
		function GetNote($index) {
			if (!$this->IsValidNoteIndex($index)) 
				return NULL;
				
			return $this->m_noteArray[$index];
		}
		 
		 
		 
		 
		 
		function Position($position=NULL, $durationType=NULL, $dotCount=NULL) {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			if (!$this->IsValidPosition($position)) return 0;
			if (!$this->IsValidDurationType($durationType)) return 0;
			 
			$this->SetDurationType($durationType);
			if ($dotCount == 1)
				$this->SetDotted();
			else if ($dotCount == 2)
			$this->SetDoubleDotted();
			 
			$this->ClearComplexSymbolArrayContents();
		}
		 
		 
		 
		// Serialization Functions
		 
		function DoSerialize(&$stream){
		 
		
			WRITE_BYTE ($stream,$this->m_position);
			WRITE_WORD ($stream,$this->m_beaming);
			WRITE_INTEGER ($stream,$this->m_data);

			$complexCount = $this->GetComplexSymbolCount();
			WRITE_BYTE ($stream,$complexCount);

			$i = 0;
			for (; $i < $complexCount; $i++) {
				WRITE_INTEGER ($stream,$this->m_complexSymbolArray[$i]);
			}

			$arr = new PowerTabArray ();
			$arr->Serialize($stream,$this->m_noteArray);
			unset ($arr);

			return 1;
		}
		
		 
		 
		 
		 
		function DoDeserialize(&$stream){
		 
		
			$this->m_position = READ_BYTE ($stream);
			$this->m_beaming = READ_WORD ($stream);
			$this->m_data = READ_INTEGER ($stream);
		 
			$complexCount = READ_BYTE ($stream);
		 
			$i = 0;
			for (; $i < $complexCount; $i++) {
		 
				$this->m_complexSymbolArray[$i] = READ_INTEGER ($stream);
		
			}
			
			$arr = new PowerTabArray ();
		 	$this->m_noteArray = $arr->DeSerialize($stream , new Note());
			unset ($arr);
		
		}
		
		 
		// Duration Type Functions
		 
		 
		 
		function SetDurationType($durationType) {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			if (!$this->IsValidDurationType($durationType)) return 0;
			 
			// Duration $type is stored in power of two format
			$this->m_data &= ~self::durationTypeMask;
			$this->m_data |= ($durationType << 24);
			 
			return 1;
		}
		 
		 
		 
		function GetDurationType() {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			return ((($this->m_data & self::durationTypeMask) >> 24));
		}
		 
		// Irregular Grouping Functions
		 
		 
		 
		 
		function SetIrregularGroupingTiming($notesPlayed, $notesPlayedOver) {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			if (!$this->IsValidIrregularGroupingTiming($notesPlayed, $notesPlayedOver)) return 0;
			 
			// Values are stored as 1-15 and 1-7
			$notesPlayed--;
			$notesPlayedOver--;
			 
			$this->m_beaming &= ~self::irregularGroupingTimingMask;
			 
			$this->m_beaming |= ($notesPlayed << 3);
			$this->m_beaming |= $notesPlayedOver;
			 
			return 1;
		}
		 
		 
		 
		 
		 
		function GetIrregularGroupingTiming(&$notesPlayed, &$notesPlayedOver) {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			 
			// Values are stored as 1-15 and 1-7, but there is no 1 value
			$notesPlayed = ((($this->m_beaming & self::irregularGroupingNotesPlayedMask) >> 3) + 1);
			$notesPlayedOver = (($this->m_beaming & self::irregularGroupingNotesPlayedOverMask) + 1);
		}
		 
		 
		 
		function HasIrregularGroupingTiming() {
			 
			//------Last Checked------//
			// - Jan 20, 2005
			$notesPlayed = 0;
			$notesPlayedOver = 0;
			$this->GetIrregularGroupingTiming($notesPlayed, $notesPlayedOver);
			return (!(($notesPlayed == 1) && ($notesPlayedOver == 1)));
		}
		 
		 
		 
		function ClearIrregularGroupingTiming() {
			 
			//------Last Checked------//
			// - Jan 20, 2005
			$this->m_beaming &= ~self::irregularGroupingTimingMask;
			return 1;
		}
		 
		// Previous Beam Duration Functions
		 
		 
		 
		function SetPreviousBeamDurationType($durationType) {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			if (!$this->IsValidPreviousBeamDurationType($durationType)) return 0;
			 
			// Clear the current $duration $type
			$this->m_beaming &= ~self::previousBeamDurationTypeMask;
			 
			$flag = 0;
			 
			if ($durationType == 8)
				$flag = self::previousBeamDuration8th;
			else if ($durationType == 16)
			$flag = self::previousBeamDuration16th;
			else if ($durationType == 32)
			$flag = self::previousBeamDuration32nd;
			else if ($durationType == 64)
			$flag = self::previousBeamDuration64th;
			 
			$this->m_beaming |= ($flag << 7);
			 
			return 1;
		}
		 
		 
		 
		function GetPreviousBeamDurationType() {
			 
			//------Last Checked------//
			// - Jan 18, 2005
			 
			$flag = (($this->m_beaming & self::previousBeamDurationTypeMask) >> 7);
			if ($flag == self::previousBeamDuration8th)
				return (8);
			else if ($flag == self::previousBeamDuration16th)
			return (16);
			else if ($flag == self::previousBeamDuration32nd)
			return (32);
			else if ($flag == self::previousBeamDuration64th)
			return (64);
			 
			return (0);
		}
		 
		// Beaming Functions
		 
		 
		 
		function SetBeamingFlag($flag) {
			 
			//------Last Checked------//
			// - Jan 7, 2005
			if (!$this->IsValidBeamingFlag($flag)) return 0;
			 
			// Mutually exclusive operations
			if (($flag & self::beamStart) == self::beamStart) {
				 
				$this->ClearBeamingFlag(self::beamEnd);
				$flag &= ~self::beamEnd;
			}
			else if (($flag & self::beamEnd) == self::beamEnd)
			$this->ClearBeamingFlag(self::beamStart);
			 
			$this->m_beaming |= $flag;
			 
			return 1;
		}
		 
		// Data Flag Functions
		 
		 
		 
		function SetDataFlag($flag) {
			 
			//------Last Checked------//
			// - Jan 7, 2005
			if (!$this->IsValidDataFlag($flag)) return 0;
			 
			// Mutually exclusive operations
			if (($flag & self::dottedMask) != 0)
				$this->ClearDataFlag(self::dottedMask);
			 
			if (($flag & self::vibratoMask) != 0)
				$this->ClearDataFlag(self::vibratoMask);
			 
			if (($flag & self::arpeggioMask) != 0)
				$this->ClearDataFlag(self::arpeggioMask);
			 
			if (($flag & self::pickStrokeMask) != 0)
				$this->ClearDataFlag(self::pickStrokeMask);
			 
			if (($flag & self::accentMask) != 0)
				$this->ClearDataFlag(self::accentMask);
			 
			if (($flag & self::tripletFeelMask) != 0)
				$this->ClearDataFlag(self::tripletFeelMask);
			 
			$this->m_data |= $flag;
			 
			return 1;
		}
		 
		// Volume Swell Functions
		 
		 
		 
		 
		 
		function SetVolumeSwell($startVolume, $endVolume, $duration) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			if (!$this->IsValidVolumeSwell($startVolume, $endVolume, $duration)) return 0;
			 
			// Construct the symbol data, then add it to the array
			$symbolData = MAKELONG(MAKEWORD($endVolume, $startVolume), MAKEWORD($duration, self::volumeSwell));
			return ($this->AddComplexSymbol($symbolData));
		}
		 
		 
		 
		 
		 
		 
		function GetVolumeSwell(&$startVolume, &$endVolume, &$duration) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			 
			$startVolume = 0;
			$endVolume = 0;
			$duration = 0;
			 
			// Get the $index of the volume swell
			$index = $this->FindComplexSymbol(self::volumeSwell);
			if ($index == -1)
				return 0;
			 
			// Get the individual pieces that make up the volume swell
			$symbolData = $this->m_complexSymbolArray[$index];
			$startVolume = HIBYTE(LOWORD($symbolData));
			$endVolume = LOBYTE(LOWORD($symbolData));
			$duration = LOBYTE(HIWORD($symbolData));
			 
			return 1;
		}
		 
		 
		 
		function HasVolumeSwell() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->FindComplexSymbol(self::volumeSwell) != -1);
		}
		 
		 
		 
		function ClearVolumeSwell() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->RemoveComplexSymbol(self::volumeSwell));
		}
		 
		// Tremolo Bar Functions
		 
		 
		 
		 
		 
		function SetTremoloBar($type, $duration, $pitch) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			if (!$this->IsValidTremoloBar($type, $duration, $pitch)) return 0;
			 
			// Construct the symbol data, then add it to the array
			$symbolData = MAKELONG(MAKEWORD($pitch, $duration), MAKEWORD($type, self::tremoloBar));
			return ($this->AddComplexSymbol($symbolData));
		}
		 
		 
		 
		 
		 
		 
		function GetTremoloBar(&$type, &$duration, &$pitch) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			 
			$type = 0;
			$duration = 0;
			$pitch = 0;
			 
			// Get the $index of the tremolo bar
			$index = $this->FindComplexSymbol(self::tremoloBar);
			if ($index == -1)
				return 0;
			 
			// Get the individual pieces that make up the tremolo bar
			$symbolData = $this->m_complexSymbolArray[$index];
			$type = LOBYTE(HIWORD($symbolData));
			$duration = HIBYTE(LOWORD($symbolData));
			$pitch = LOBYTE(LOWORD($symbolData));
			 
			return 1;
		}
		 
		 
		 
		function HasTremoloBar() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->FindComplexSymbol(self::tremoloBar) != -1);
		}
		 
		 
		 
		function ClearTremoloBar() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->RemoveComplexSymbol(self::tremoloBar));
		}
		 
		// Multibar Rest Functions
		 
		 
		 
		function SetMultibarRest($measureCount) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			if (!$this->IsValidMultibarRest($measureCount)) return 0;
			 
			// Construct the symbol data, then add it to the array
			$symbolData = MAKELONG(MAKEWORD($measureCount, 0), MAKEWORD(0, self::multibarRest));
			return ($this->AddComplexSymbol($symbolData));
		}
		 
		 
		 
		 
		function GetMultibarRest(&$measureCount) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			 
			$measureCount = 0;
			 
			// Get the $index of the multibar self::rest
			$index = $this->FindComplexSymbol(self::multibarRest);
			if ($index == -1)
				return 0;
			 
			// Get the individual pieces that make up the multibar self::rest
			$symbolData = $this->m_complexSymbolArray[$index];
			$measureCount = LOBYTE(LOWORD($symbolData));
			 
			return 1;
		}
		 
		 
		 
		function HasMultibarRest() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->FindComplexSymbol(self::multibarRest) != -1);
		}
		 
		 
		 
		function ClearMultibarRest() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			return ($this->RemoveComplexSymbol(self::multibarRest));
		}
		 
		// Complex Symbol Array Functions
		 
		 
		 
		function AddComplexSymbol($symbolData) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			 
			// Get and validate the symbol $type
			$type = HIBYTE(HIWORD($symbolData));
			if (!$this->IsValidComplexSymbolType($type)) return 0;
			 
			$returnValue = 0;
			 
			// Get the $index in the complex array where the symbol is stored
			$index = $this->FindComplexSymbol($type);
			 
			// Found symbol in the array, update the symbol data
			if ($index != -1) {
				 
				$this->m_complexSymbolArray[$index] = $symbolData;
				$returnValue = true;
			} else {
				// Symbol was not found in the array, find the first free array slot and insert there
				$i = 0;
				for (; $i < MAX_POSITION_COMPLEX_SYMBOLS; $i++) {
					 
					if ($this->m_complexSymbolArray[$i] == self::notUsed) {
						 
						$this->m_complexSymbolArray[$i] = $symbolData;
						$returnValue = true;
						break;
					}
				}
			}
			 
			return ($returnValue);
		}
		 
		 
		 
		function GetComplexSymbolCount() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			$returnValue = 0;
			$i = 0;
			for (; $i < MAX_POSITION_COMPLEX_SYMBOLS; $i++) {
				 
				// Slot is not used; break out
				if ($this->m_complexSymbolArray[$i] == self::notUsed)
					break;
				$returnValue++;
			}
			return ($returnValue);
		}
		 
		 
		 
		 
		function FindComplexSymbol($type) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			$returnValue = -1;
			 
			$i = 0;
			for (; $i < MAX_POSITION_COMPLEX_SYMBOLS; $i++) {
				 
				// Found the symbol $type; break out
				if (HIBYTE(HIWORD($this->m_complexSymbolArray[$i])) == $type) {
					 
					$returnValue = $i;
					break;
				}
			}
			
			return ($returnValue);
		}
		 
		 
		 
		 
		function RemoveComplexSymbol($type) {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			$returnValue = 0;
			 
			$i = 0;
			for (; $i < MAX_POSITION_COMPLEX_SYMBOLS; $i++) {
				 
				if (HIBYTE(HIWORD($this->m_complexSymbolArray[$i])) == $type) {
					 
					$this->m_complexSymbolArray[$i] = self::notUsed;
					$returnValue = true;
					break;
				}
			}
			 
			return ($returnValue);
		}
		 
		 
		function ClearComplexSymbolArrayContents() {
			 
			//------Last Checked------//
			// - Jan 19, 2005
			$i = 0;
			for (; $i < MAX_POSITION_COMPLEX_SYMBOLS; $i++)
			$this->m_complexSymbolArray[$i] = self::notUsed;
		}
		 
		 
	}
	 
?>

